/*
    A lightweight HTTP request library for Linux
    Copyright (C) 2024  Liu Tianran

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
#ifndef C_HTTP_REQUEST_LIU_C_HTTP_REQUEST_H
#define C_HTTP_REQUEST_LIU_C_HTTP_REQUEST_H

#include <netdb.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <arpa/inet.h>
#include <sys/socket.h>

#define END_KEY "#END-KEY#"

#define END_HEADERS {END_KEY,  ""}
#define HEADERS (header [])
#define REQUEST & (request)

#define RES_CALLBACK_ARGUMENTS lchr_http_req_err err, char *req_str, char *res_str, request *req, response *res, int sock_fd

#define CLEAN_ALLOC free(req_str), free(res_str), lchr_destroy_res_obj(res);
#define CLOSE_SOCKET close(sock_fd);
#define CLEAN_ALLOC_AND_CLOSE_SOCKET CLEAN_ALLOC CLOSE_SOCKET

typedef struct {
    char *key, *value;
} header;

typedef struct {
    char *method, *path;
    unsigned short port;
    header *headers;
    char *body;
} request;

typedef struct {
    char *http_version, *status_code, *status_message, *body;
    header *headers;
} response;

typedef enum {
    HTTP_REQ_ERR_NORMAL = 0,
    HTTP_REQ_ERR_ALLOC_FAILED = 1,
    HTTP_REQ_ERR_SOCKET_CREATION_FAILED = 2,
    HTTP_REQ_ERR_NO_SUCH_HOST = 3,
    HTTP_REQ_ERR_CONNECTION_FAILED = 4,
    HTTP_REQ_ERR_SEND_FAILED = 5,
    HTTP_REQ_ERR_RECV_FAILED = 6,
} lchr_http_req_err;

typedef void (*response_callback)(lchr_http_req_err, char *, char *, request *, response *, int);

__attribute__((unused))
int lchr_is_headers_reach_end(header *headers);

__attribute__((unused))
char *lchr_headers_get(header *headers, char *key);

__attribute__((unused))
header *lchr_headers(void *end_pos, ...);

__attribute__((unused))
void lchr_set_response_buffer_size(size_t buffer_size);

__attribute__((unused))
void lchr_destroy_headers(header *headers);

__attribute__((unused))
void lchr_destroy_res_obj(response *res);

__attribute__((unused))
void lchr_empty_res_cb(RES_CALLBACK_ARGUMENTS);

__attribute__((unused))
void lchr_res_cb_clean_alloc(RES_CALLBACK_ARGUMENTS);

__attribute__((unused))
void lchr_res_cb_close_socket(RES_CALLBACK_ARGUMENTS);

__attribute__((unused))
void lchr_res_cb_clean_alloc_and_close_socket(RES_CALLBACK_ARGUMENTS);

__attribute__((unused))
response *lchr_http_request(request *request_obj, response_callback res_cb);

#endif
